/*
 * G3DMImporter.cpp
 *
 *  Created on: Jan 24, 2014
 *      Author: knuke
 */

#include "G3DMImporter.hpp"
#include "Model.hpp"
#include "Node.hpp"
#include "Material.hpp"
#include "Mesh.hpp"
#include "Color4f.hpp"
#include "BinaryStreamReader.hpp"
#include <GMath/GMath.hpp>
#include <string>
#include <iostream>
#include <vector>

using std::string;
using std::vector;
using gmath::Vec3f;

namespace gengine
{

  G3DMImporter::G3DMImporter() :
      model_(0)
  {

  }

  G3DMImporter::~G3DMImporter() throw ()
  {

  }

  Model* G3DMImporter::importFile(string file_name)
  {
    reader_.fromFile(file_name);

    model_ = new Model();

    uint mat_cnt = reader_.nextInt(4);
    COUNTER_LOOP(mat_idx, 0, mat_cnt)
    {
      Material* mat = importMaterial();
      model_->addMaterial(mat);
    }

    uint mesh_cnt = reader_.nextInt(4);
    COUNTER_LOOP(mesh_idx, 0, mesh_cnt)
    {
      Mesh* mesh = importMesh();
      model_->addMesh(mesh);
    }

    Node* root = importNode();
    model_->setRootNode(root);

    return model_;
  }

  Material* G3DMImporter::importMaterial()
  {
    Material* mat = new Material();

    float alpha = reader_.nextFloat();

    vector<float> ambient = reader_.nextFloatArrray(3);
    vector<float> diffuse = reader_.nextFloatArrray(3);

    ambient.push_back(alpha);
    Color4f ambientCol(ambient.data());
    mat->setAmbient(ambientCol);

    diffuse.push_back(alpha);
    Color4f diffuseCol(diffuse.data());
    mat->setDiffuse(diffuseCol);

    return mat;
  }

  Mesh* G3DMImporter::importMesh()
  {
    Mesh* mesh = new Mesh();

    uint index_size = reader_.nextInt(4);

    uint v_cnt = reader_.nextInt(index_size);
    COUNTER_LOOP(v_idx, 0, v_cnt)
    {
      vector<float> v_dat = reader_.nextFloatArrray(3);
      Vec3f v(&v_dat[0]);
      mesh->addVertex(v);
    }

    uint mat_grp_cnt = reader_.nextInt(4);
    COUNTER_LOOP(mat_grp_idx, 0, mat_grp_cnt)
    {
      MaterialGroup mat_grp(mesh);

      uint mat_idx = reader_.nextInt(4);
      const Material* mat = model_->getMaterial(mat_idx);
      mat_grp.setMaterial(mat);

      uint tri_cnt = reader_.nextInt(4);
      COUNTER_LOOP(tri_idx, 0, tri_cnt)
      {
        vector<int> tri_dat = reader_.nextIntArrray(3, index_size);
      }

      mesh->addMaterialGroup(mat_grp);
    }

    return mesh;
  }

  Node* G3DMImporter::importNode()
  {
    Node* node = new Node();

    uint mesh_cnt = reader_.nextInt(4);
    COUNTER_LOOP(mesh_idx, 0, mesh_cnt)
    {
      uint mesh_id = reader_.nextInt(4);
    }
    uint child_cnt = reader_.nextInt(4);
    COUNTER_LOOP(child_idx, 0, child_cnt)
    {
      Node* child = importNode();
      node->addChild(child);
    }

    return node;
  }

} /* namespace gengine */
